package cn.walls1717.juc.lock;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * 8锁案例<br>
 *
 * 总结：<br>
 * 1-2：一个对象里面如果有多个synchronized方法，那么同时只能有一个线程进入对象的synchronized方法，
 * synchronized加在方法上锁的是this当前对象。<br>
 * 3-4：3因为hello方法是普通方法，没有发生锁竞争；4因为synchronized方法锁的是当前this对象，两个对象自然不会发生锁竞争。<br>
 * 5-6：静态同步方法锁的是类class，普通同步代码块锁的是当前实例对象this，同步方法块锁的是synchronized括号内的对象。<br>
 * 7-8：静态同步方法锁的是类class，普通同步代码块锁的是当前实例对象this，所以说一个静态同步方法与一个普通同步方法的同时调用
 * 并不会竞争同一把锁，不会发生锁竞争。
 *
 * @author walls1717
 * @create 2022/12/09 20:34
 **/
@Slf4j
public class Lock8Demo {

    public static void main(String[] args) throws InterruptedException {
        /*
         * 1.有t1，t2两个线程，先打印邮件还是短信？ 邮件
         * 2.sendEmail方法加入暂停3s，先打印邮件还是短信？ 邮件
         * 3.添加一个普通的hello方法，先打印邮件还是hello？ hello
         * 4.2部手机，先打印邮件还是短信？ 短信
         * 5.2个静态同步方法，1部手机，先打印邮件还是短信？ 邮件
         * 6.2个静态同步方法，2部手机，先打印邮件还是短信？ 邮件
         * 7.1个静态同步方法，1个普通同步方法，1部手机，先打印邮件还是短信？ 短信
         * 8.1个静态同步方法，1个普通同步方法，2部手机，先打印邮件还是短信？ 短信
         */
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        new Thread(() -> {
            phone.sendEmail();
        }, "t1").start();

        TimeUnit.MILLISECONDS.sleep(200);

        new Thread(() -> {
            phone.sendSms();
            // phone.hello();
            // phone2.sendSms();
        }, "t2").start();
    }
}

@Slf4j
class Phone {
    public static synchronized void sendEmail() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("发送邮件");
    }

    public synchronized void sendSms() {
        log.info("发送短信");
    }

    public void hello() {
        log.info("hello");
    }
}
